<?php
/**
 Create this file for validating the comfair algorithm.
 Create the data array to substitute the query
  
 will be making use of these array:
  $group_current_members
  $group_info_arr, $group_exclude_list, $group_rank_list,
  $people_info_arr,$people_max_com_num, $people_pref_list
 */
function _shms_comfair_array_has_rank_1($arr){
  return array_key_exists(1, $arr);
}

function load_from_file($file_name){
  $file = file_get_contents($file_name);
  $lines = explode("\n",$file);
  $arr = array();
  foreach($lines as $line){
    $line_arr = explode(" ",$line);
    if(empty($line_arr[0]))  continue;
    $id = $line_arr[0]; $arr[$id] = array();
    for($i = 1; $i < sizeof($line_arr); $i++){
      // index should starting from 1
      if(!isset($arr[$id][1])) $arr[$id][1] = $line_arr[$i];
      else $arr[$id][] = $line_arr[$i];
    }
  }
  return $arr;
}

$group_current_members = load_from_file("group_current_member.txt");

// Self wrote of the load_person part
$fp = fopen("pinfo.csv","r");
$people_info_arr = array();
$people_max_com_num = array();
$line = fgetcsv($fp); // skip the first line
while($line = fgetcsv($fp)){
  $people_info_arr[$line[2]] = array(
    'fullname' => $line[0],
    'pid' => $line[1],
    'pyid' => $line[2],
  );
  $people_max_com_num[$line[2]] = $line[3];
}

$fp = fopen("ginfo.csv","r");
$line = fgetcsv($fp); // skip the first line
// and randomly assign a chair_pid
$group_info_arr = array();
while($line = fgetcsv($fp)){
  $group_info_arr[$line[2]] = array(
    'name' => $line[0],
    'gid' => $line[1],
    'gyid' => $line[2],
    'quota' => $line[4],
  );
}

  $group_exclude_list = load_from_file("exclude_lst.txt");
  $group_rank_list = load_from_file("group_pref.txt");
  $people_pref_list = load_from_file("people_pref.txt");

    // ready to run the algorithm now :)
/*
 * 1. people's first choice would be fulfilled, based on random order.
 *    coms would be filled with people in random order, until it's full
 * 2. if coms still got open space, go select the people, who also selected 
 *    this comn and haven't exceed its maximum prefered comns yet, in comns' 
 *    preference list, in the order of preference.
 * 3. download the thing as excel
 */
  $people_groups = array();
  foreach($group_current_members as $gyid => $lst){
    foreach($lst as $pyid){
      $people_groups[$pyid][] = $gyid;
    }
  }

  // load current group config into group_members, and save in person_groups table 
  // correspondingly
  $group_members = $group_current_members;
  
  /*
  print("The already ins:\n");
  print("People:\n");                 // TODO: this part is for
  print_r($people_groups);            // TODO:  TESTING ONLY
  print("\nGroups:\n");               // TODO: to remove later
  print_r($group_members);
  print("-----------我是华丽的分割线~：）--------------\n");
   */

  // assign the first rank.
  // it's possible that people has already been assigned with a com
  $filtered_arr = array_filter($people_pref_list,"_shms_comfair_array_has_rank_1");
  $plist_random = array_keys($filtered_arr);
  shuffle($plist_random);
  foreach($plist_random as $pyid){
    // print("processing person $pyid now.\n");
    if($people_max_com_num[$pyid] <= sizeof($people_groups[$pyid])){  // if the people has full joined.
      // print("person with id $pyid don't want to join any\n");
      continue; // if the person do not want to join any
    }
    $prefered_group_gyid = $people_pref_list[$pyid][1];
     // if excluded by group then simply skip
    if(isset($group_exclude_list[$prefered_group_gyid]) && in_array($pyid, $group_exclude_list[$prefered_group_gyid])){
      // print("person $pyid exclueded by group $prefered_group_gyid \n");
      continue;
    }
    if(isset($group_members[$prefered_group_gyid]) &&  // if the group is full
      (sizeof($group_members[$prefered_group_gyid]) >= $group_info_arr[$prefered_group_gyid]['quota'])) continue;
    
    // excluded all possible problem already... now do the assigning.
    $group_members[$prefered_group_gyid][] = $pyid;
    $people_groups[$pyid][] = $prefered_group_gyid;
  }
  
  // get a list of groups which haven't exceeded their quota yet
  $groups_to_fill = array_keys($group_rank_list);
    // filter out the already_full groups
  $groups_to_remove = array();
  foreach($groups_to_fill as $key => $gyid){
    if(isset($group_members[$gyid]) &&
       (sizeof($group_members[$gyid]) >= $group_info_arr[$gyid]['quota'])){
        $groups_to_remove[] = $key;
        //printf("group id: %d, quota %d, current member size: %d\n",$gyid,$group_info_arr[$gyid]['quota'],sizeof($group_members[$gyid]));
    }
  }
  foreach($groups_to_remove as $key) unset($groups_to_fill[$key]);

  // starting by checking rank 2
  $groups_processing_rank = array_fill_keys($groups_to_fill, 2);  

  // now check the groups according to their preferred list of people
  $has_changed = TRUE;
  while(!empty($groups_to_fill) && $has_changed){  // run as long as got group unassigned.
    $has_changed = FALSE;  // would remark it as true whenever there's any group info
    // loop through the groups once and assign
    shuffle($groups_to_fill); // each time shuffle to keep fairness
    $groups_to_remove = array();
    foreach($groups_to_fill as $key=>$gyid){
      // try fill one member according to groups's and person's willingness: in the order of group's rank,
      // select the people which also selected the group, even if it's in the group's exclude list.
      //    (cuz group selected the person in the first place.)
      
      // proceed the groups's rank list by 1 each time;
      // but in the case person being selected already, proceed by 1 another time, until person is selected.
      while($groups_processing_rank[$gyid] <= sizeof($group_rank_list[$gyid])){
        $consider_pyid = $group_rank_list[$gyid][$groups_processing_rank[$gyid]++]; // auto proceed
        if(!in_array($consider_pyid,$group_members[$gyid])  // non in that group yet
          && sizeof($people_groups[$consider_pyid]) < $people_max_com_num[$consider_pyid] // strictly less
        ){ // would fill it
          $people_groups[$consider_pyid][] = $gyid;
          $group_members[$gyid][] = $consider_pyid;
          $has_changed = TRUE; // 
          break;
        }
      }
      if(sizeof($group_members[$gyid]) >= $group_info_arr[$gyid]['quota']){
        $groups_to_remove[] = $key;
      }
    }

    // then remove the already filled groups
    foreach($groups_to_remove as $key)  unset($groups_to_fill[$key]);
  }

  // then present the result
  print("People's maximum groups\n");
  print_r($people_max_com_num);
  print("Groups to fill arr: \n");
  print_r($groups_to_fill);
  print("\nPerson in group: \n");
  print_r($people_groups);
  print("\nGroup's Member:\n");
  print_r($group_members);
  print("\nPeople's pref\n");
  /*
  print_r($people_pref_list);
  print("\nGroup's pref\n");
  print_r($group_rank_list);
  */
